package com.xinqi.gateway.filter;

import cn.dev33.satoken.exception.NotLoginException;
import cn.dev33.satoken.reactor.filter.SaReactorFilter;
import cn.dev33.satoken.router.SaRouter;
import com.xinqi.common.base.error.CommonErrors;
import com.xinqi.common.base.utils.json.JSON;
import com.xinqi.common.satoken.utils.LoginHelper;
import com.xinqi.gateway.config.properties.IgnoreWhiteProperties;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

/**
 * [Sa-Token 权限认证] 拦截器
 *
 * @author dgyu
 */
@Slf4j
@Configuration
public class AuthFilter {

    /**
     * 注册 Sa-Token 全局过滤器
     */
    @Bean
    public SaReactorFilter getSaReactorFilter(IgnoreWhiteProperties ignoreWhite) {
        return new SaReactorFilter()
            // 拦截地址
            .addInclude("/**")
            // 排除地址
            .addExclude("/favicon.ico", "/actuator/**")
            // 鉴权方法：每次访问进入
            .setAuth(obj -> {
                // 登录校验 -- 拦截所有路由
                SaRouter.match("/**")
                    // 白名单地址，不需要校验的地址
                    .notMatch(ignoreWhite.getWhites())
                    .check(r -> {
                        // 检查是否登录（是否有Token）
                        LoginHelper.checkLogin();
                    });
                // 角色校验 -- 拦截以 admin 开头的路由，必须具备 admin 角色或者 super-admin 角色才可以通过认证
                SaRouter.match("/*/admin/**", r -> CommonErrors.FORBIDDEN.check(LoginHelper.isAdmin(), "该用户不是管理员"));
            }).setError(e -> {
                log.error("认证错误！", e);
                String msg;
                if (e instanceof NotLoginException) {
                    NotLoginException notLogin = (NotLoginException) e;
                    msg = notLogin.getMessage();
                } else {
                    msg = "认证失败，无法访问系统资源";
                }
                return JSON.stringify(CommonErrors.UNAUTHORIZED.withMessage(msg).asResult());
            });
    }
}
